package org.gwu.seuss.ui;

import java.io.IOException;
import java.util.Properties;

import org.gwu.seuss.communication.request.ClientRequest;
import org.gwu.seuss.communication.request.ServerResponse;
import org.gwu.seuss.communication.sockets.ssl.Util;
import org.gwu.seuss.ui.commandline.BaseCommandLineArgs;
import org.gwu.seuss.ui.connection.ConnectionHandler;
import org.gwu.seuss.ui.exception.NoArgumentsProvidedException;
import org.gwu.seuss.ui.exception.TooManyArgumentsException;
import org.gwu.seuss.ui.validator.RequestValidator;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;

public abstract class CommandLineInterface {

	private static final String HOST = "server.host";
	private static final String PORT = "server.port";
	protected ConnectionHandler connectionHandler;
	protected RequestValidator validator;
	protected BaseCommandLineArgs bcla;
	protected CmdLineParser parser;

	public String doRequest(String[] args) {
		init();
		String responseText = "";

		// console width for output
		parser.setUsageWidth(80);

		try {
			parser.parseArgument(args);

			if (bcla.isHelp()) {
				parser.printUsage(System.out);
			} else {
				// validate arguments
				if (validator.isValid(bcla)) {

					Properties connectionProps = Util
							.loadPropertiesFromResource(getConnectionProperties());

					connectionHandler
							.makeConnection(getPropertiesFile(),
									connectionProps.getProperty(HOST), Integer
											.parseInt(connectionProps
													.getProperty(PORT)), bcla
											.getKey().toCharArray());

					// relay arguments / handle response
					ClientRequest cr = getClientRequest(bcla);
					ServerResponse response = connectionHandler.sendRequest(cr);

					responseText = response.isSuccess() ? handleServerResponse(
							cr, response) : response.getMessage();

				} else {
					responseText = validator.getErrorMessage();
				}
			}

		} catch (CmdLineException cle) {
			log(cle.getMessage());
			bcla.printError("Command line arguments incomplete", parser);
		} catch (NoArgumentsProvidedException nape) {
			log(nape.getMessage());
			bcla.printError("no action / arguments provided", parser);
		} catch (TooManyArgumentsException tae) {
			log(tae.getMessage());
			bcla.printError("Too many actions / arguments requested", parser);
		} catch (Exception e) {
			log(e.getMessage());
			bcla.printError("Error performing action", parser);
		}
		return responseText;
	}

	protected ClientRequest setUpClientRequest(BaseCommandLineArgs cla) {
		ClientRequest cr = new ClientRequest();
		cr.setUsername(cla.getLogin());
		cr.setPassword(cla.getPassword());
		return cr;
	}

	// TODO: Spring like stuff
	public abstract void init();

	public abstract String handleServerResponse(ClientRequest cr,
			ServerResponse sr) throws Exception;

	public abstract <T extends BaseCommandLineArgs> ClientRequest getClientRequest(
			T cla) throws IOException, NoArgumentsProvidedException;

	private void log(String message) {
		// TODO: logging
	}

	public String getConnectionProperties(){
		return "connection.properties";
	}
	
	public abstract String getPropertiesFile();



}
